namespace X {
  function m(value) { // enumerable
    return function (target, key) {
      const outerDescriptor = Object.getOwnPropertyDescriptor(target, key)
      if (!outerDescriptor) {
        Object.defineProperty(target, key, {
          get() {
            return undefined
          },
          set(val) {
            const classDescriptor = Object.getOwnPropertyDescriptor(target, key)
            console.log('==', classDescriptor)
            Object.defineProperty(this, key, {
              value: val,
              writable: true,
              enumerable: classDescriptor.enumerable,
              configurable: classDescriptor.configurable,
            })
          },
          configurable: true,
          enumerable: value,
        })
      } else {
        outerDescriptor.enumerable = value
      }
      console.log('===', Object.getOwnPropertyDescriptor(target, key))
    }
  }

  function n(value) { // configurable
    return function (target, key) {
      const outerDescriptor = Object.getOwnPropertyDescriptor(target, key)
      if (!outerDescriptor) {
        Object.defineProperty(target, key, {
          get() {
            return undefined
          },
          set(val) {
            const classDescriptor = Object.getOwnPropertyDescriptor(target, key)
            console.log('--', classDescriptor)
            Object.defineProperty(this, key, {
              value: val,
              writable: true,
              enumerable: classDescriptor.enumerable,
              configurable: classDescriptor.configurable,
            })
          },
          configurable: value,
          enumerable: true,
        })
      } else {
        console.log('----', value)
        outerDescriptor.configurable = value
      }
      console.log('---', Object.getOwnPropertyDescriptor(target, key))
    }
  }

  class My {
    @n(false)
    @m(false)
    a = 1

    b = 2
  }

  const my = new My()

  console.log(Object.getOwnPropertyDescriptor(my, 'a'))
  // console.log(my.a)
  // console.log(Object.getOwnPropertyDescriptor(My, 'a'))
  // my.a = 1
  // console.log(Object.getOwnPropertyDescriptor(My, 'a'))
  // my.a = 2
  // console.log(Object.getOwnPropertyDescriptor(My, 'a'))

  for (const a in my) {
    console.log('~', my[ a ])
  }
}
